﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web;
using System.Net;
using yq.ControllerBase;
using yq.ControllerBase.CaChe;
using yq.Model.Logic;
using System.ComponentModel.DataAnnotations;

namespace yq.ControllerBase
{
    /// <summary>
    /// 控制器基类 
    /// </summary>
    public abstract class BaseController : Controller
    {
        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <returns></returns>
        public static CurrentUser GetCurrentUser
        {
            get
            {
                return new CurrentUser();
            }
        }

        /// <summary>
        /// 当前上下文
        /// </summary>
        private ActionExecutingContext context;

        /// <summary>
        /// 重写方法，在运行Action方法前调用
        /// 权限判断
        /// </summary>
        /// <param name="filterContext">上下文信息</param>
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            context = filterContext;

           //权限判断
            System.Web.Routing.RouteData RouteData = filterContext.RouteData;

            string area = RouteData.DataTokens["Area"] == null ? "Home" : RouteData.DataTokens["Area"].ToString();// 区域
            string controller = RouteData.Values["controller"].ToString();// 当前控制器
            string action = RouteData.Values["action"].ToString();// 方法
        

            //系统是否初始化过
            if (WebConfig.WebId.Length == 0)
            {
                WebConfig.WebId = yq.GetService.Create<yq.IService.ISys>().Initialize().Value;

                if (WebConfig.WebId.Length == 0 && !action.ExtEquals("Initialize") && !action.ExtEquals("DoInitialize"))
                {
                    filterContext.Result = new RedirectResult("~/Home/Home/Initialize");
                }
            }
            else
            {
                filterContext.Controller.ViewBag.Title = yq.Model.Logic.SysInfo.Load(WebConfig.WebId).Title;
            }

            //检测是否设置了跳过权限验证的
            if (IsExistAttribute<NoPurviewFilterAttribute>(filterContext.ActionDescriptor))
            {
                base.OnActionExecuting(filterContext);
                return;
            }

            //权限页面
            PurviewPage page = new PurviewPage();

            if (IsPurview(action, controller, area, out  page) == false)
            {
                if (GetCurrentUser.IsLogin)
                {
                    var resultError = ErrorFilterAttribute.GetError(ErrorFilterType.Default, "权限不足", filterContext.Controller);
                    filterContext.Result = resultError;
                }
                else
                {
                    if (this.ControllerContext.IsChildAction)
                    {
                        filterContext.Result = new ContentResult() { Content = "请重新登录" };
                    }
                    else
                    {
                        filterContext.Result = new RedirectResult("~/Home/Home/Login");
                    }
                }
            }
            else
            {
                if (this.ControllerContext.IsChildAction==false)
                {
                    //上级的名称
                    string purviewkey = (area + "/" + controller).ToUpper().ExtMD5();
                    var pageSuperior = new PurviewCaChe().ReadCache<PurviewPage>(purviewkey);
                    filterContext.Controller.TempData["SuperiorHeadTitle"] = pageSuperior.Name;
                    filterContext.Controller.TempData["HeadTitle"] = page.Name;
                    filterContext.Controller.ViewBag.Title += ("--" + page.Name);
                }

                base.OnActionExecuting(filterContext);
            }
        }

        /// <summary>
        /// 判断是否有权限
        /// </summary>
        /// <param name="action"></param>
        /// <param name="controller"></param>
        /// <param name="area"></param>
        /// <returns></returns>
        public static bool IsPurview(string action, string controller, string area, out PurviewPage page)
        {
            //生成权限路径Id
            string purviewkey = (area + "/" + controller + "/" + action).ToUpper().ExtMD5();

            //查询当前页面的权限
            page = new PurviewCaChe().ReadCache<PurviewPage>(purviewkey);

            //特殊权限配置
            var purviewType = GetCurrentUser.GetPurview(purviewkey);

            if (purviewType != Enums.PurviewException.Type.Add)
            {
                if (page.PurviewEnum.GetHashCode() > GetCurrentUser.PurviewEnum.GetHashCode() || purviewType == Enums.PurviewException.Type.Exclude)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 方法内是否包含这个特性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        private bool IsExistAttribute<T>(ActionDescriptor action) where T : class
        {
            //获取权限数据
            object[] attributes = action.GetCustomAttributes(typeof(T), true);
            if (attributes != null && attributes.Length > 0)
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// 获取VerifyFilter中使用过的对象
        /// </summary>
        /// <returns></returns>
        public T GetModel<T>() where T :  yq.Basis.ModelBase<T>, new()
        {
            ViewDataDictionary ViewData=context.Controller.ViewData;

            var info= ViewData[VerifyFilterAttribute.KeyString] as T;

            if (info == null && ViewData.ContainsKey(VerifyFilterAttribute.RequestDataId))
            {    
                //如果viewdata没加载到数据去数据库加载一次
                string requestDataId = ViewData[VerifyFilterAttribute.RequestDataId].ToString() ;
                string id = context.HttpContext.Request[requestDataId];
                info = yq.Basis.ModelBase<T>.Load(id);
            }

            return info;
        }

        /// <summary>
        /// 说明：异常处理，为了统一返回json,拦截发生的异常
        /// 创建人：邓毅泉 
        /// 创建日期：2012/12/5 9:31:02
        /// </summary>
        /// <param name="filterContext"></param>
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            ///异常检测
            ErrorFilterAttribute efa = new ErrorFilterAttribute();
            efa.OnAction(filterContext);
        }


        /// <summary>
        /// TryUpdateModel 只验证Request.Form传入的数据
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="model">更新的对象</param>
        /// <param name="requestForm">页面 this.Request.Form 集合</param>
        /// <param name="prefix">前缀名</param>
        /// <returns></returns>
        public bool TryUpdateModel<TModel>(
            TModel model,
            System.Collections.Specialized.NameValueCollection requestForm,
            string prefix = null) where TModel : class
        {
            bool outbool = true;
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            IValueProvider valueProvider = ValueProviderFactories.Factories.GetValueProvider(ControllerContext);

            Predicate<string> propertyFilter = propertyName => true;
            IModelBinder binder = Binders.GetBinder(typeof(TModel));

            ModelBindingContext bindingContext = new ModelBindingContext()
            {
                ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)),
                ModelName = prefix,
                ModelState = ModelState,
                PropertyFilter = propertyFilter,
                ValueProvider = valueProvider
            };
            binder.BindModel(ControllerContext, bindingContext);

            var metadataTypeAttribute = (MetadataTypeAttribute)bindingContext.ModelMetadata.ModelType.GetCustomAttributes(typeof(MetadataTypeAttribute), false)[0];
            foreach (string key in ModelState.Keys)
            {
                //如果有错误 并且在form中也有这个数据
                if (ModelState[key].Errors.Count > 0 && requestForm[key] != null)
                {
                    outbool = false;
                    break;
                }
            }
            return outbool;
        }

    }
}
